#include "data.h"
#include "helpers.h"
#include "polygon.h"
#include "layer_graph.h"
#include "opp_graph.h"
#include "input.h"

#include "..\slice\visual.h"
#include "..\slice\sample_on_ball.h"

clock_t start_time, end_time;
clock_t start_time_2, end_time_2;

#define DEFAULT_PRINTING_DIRECTION 1
double time_curved = 0;
int main()
{
	start_time = clock();
	nozzle the_nozzle;
	the_nozzle.upper_surface_r = 4.5; // 4.5
	the_nozzle.lowwer_surface_r = 1;  //1
	the_nozzle.nozzle__H_total =8;  //8
	the_nozzle.nozzle_H_half = 2.5; //2.5

	Input input;
	input.config_path = "..\\src\\slice\\config.ini";
	input.model_path = "..\\model\\cloth.stl";
	
	std::vector<Data> data;

#if DEFAULT_PRINTING_DIRECTION

	input.DefaultPrintingDirectionSlice();
	data.resize(1);
	data[0].ReadData("slice_layers.txt");

	Layer_Graph layer_graph(data[0]);
	layer_graph.BuildLayerGraph(the_nozzle);
	layer_graph.GetInitialOPP();

	OPP_Graph opp_graph(data[0], layer_graph.initial_opp_info, layer_graph.temp_edges,layer_graph.cont_normal_dependency_edges);
	opp_graph.BuildOPPGraph_G0();

	opp_graph.MergeOPP_First_ALL_SearchTree();

	Layer_Graph layer_graph_2(data[0]);
	layer_graph_2.BuildLayerGraphWithoutCollsion(the_nozzle);
	layer_graph_2.GetInitialOPP();
	int cont_call_curvislicer = 0;
	start_time_2 = clock();

	opp_graph.GeneratePatches();
	opp_graph.GeneratePath();

	connect_by_zigzag_and_spiral(5,true, 1,true);   //5

		

#else
	start_time = clock();
	//input.SamplingPrintingDirectionSlice();
	std::vector<int> _index;
	std::vector<double> support_points_num;
	std::vector<double> flatten_area;
	std::vector<int> G0_points_num;
	std::vector<bool> is_deleted;
	for (int i = 0; i < total_directions; i++) {
		Data _data;
		_data.ReadData("..\\model\\slice_layer\\"+ file_name+"\\slice_layers" + std::to_string(i) + suffix_txt);
		int sum_slice_point = 0;
		int num = input.JudgeSupportFallOnGround(_data, sum_slice_point);
		if (num != -1) {
			double temp_num = num;
			temp_num = temp_num / double(num + sum_slice_point);
			support_points_num.push_back(temp_num);
			data.push_back(_data);

			Layer_Graph layer_graph(_data);
			layer_graph.BuildLayerGraph();
			layer_graph.GetInitialOPP();
			G0_points_num.push_back(layer_graph.initial_opp_info.size());
			_index.push_back(i);
			is_deleted.push_back(true);

			char _model_path[50] = "..\\model\\diff_dir\\";
			strcat(_model_path, (file_name + "\\" + std::to_string(i) + suffix_stl).c_str());
			//std::cout << _model_path << std::endl;
			double _flatten_area = input.CalculateFlattenArea(std::string(_model_path));
			flatten_area.push_back(_flatten_area);

			std::cout << i << ": " <<  "flatten_area " << _flatten_area << " G0 points num: " << G0_points_num[G0_points_num.size() - 1] << " " << "support points num " << temp_num << std::endl;
		}
	}
	//return 0;
	/*for (int i = 0; i < G0_points_num.size(); i++) {
		for (int j = 0; j < G0_points_num.size(); j++) {
			if (i == j) continue;
			if (flatten_area[j] <= flatten_area[i] && support_points_num[j] <= support_points_num[i]) {
				is_deleted[i] = true;
				break;
			}
		}
	}*/

	double weight_1 =0.8;
	//double weight_2 = 1;
	int choose_orientation_number = 10;
	vector<double> sum_value;
	sum_value.resize(G0_points_num.size());
	for (int i = 0;i < G0_points_num.size();i++) {
		sum_value[i] = weight_1 * flatten_area[i] + (1- weight_1) * support_points_num[i];
	}
	vector<double> temp_sum_value = sum_value;
	vector<double>::iterator start_sum_value = sum_value.begin();
	vector<double>::iterator end_sum_value = sum_value.end();
	/*double min_E = 999999;
	int index;
	for (int i = 0;i < sum_value.size();i++)

		if (sum_value[i] < min_E) {
			min_E = min(min_E, sum_value[i]);
			index = i;
		}*/
	std::sort(start_sum_value, end_sum_value);
	//std::reverse(start_sum_value, end_sum_value);
	for (int i = 0;i < choose_orientation_number;i++) {
		for (int j = 0;j < temp_sum_value.size();j++) {
			if (sum_value[i] == temp_sum_value[j]) {
				is_deleted[j] = false;
				break;
			}
		}
	}
	end_time = clock();
	std::cout << "orientation time = " << double(end_time - start_time) / CLOCKS_PER_SEC << "s" << std::endl;
	std::cout << "*****************************choose*******************************" << std::endl;
	for (int i = 0; i < G0_points_num.size(); i++) {
		if (!is_deleted[i]) {
			if (_index[i] == 5 || _index[i] == 37 || _index[i] == 45 || _index[i] == 61 || _index[i] == 87 || _index[i] == 101 || _index[i] == 143 || _index[i] == 160 || _index[i] == 161 || _index[i] == 197
				|| _index[i] == 238 || _index[i] == 285 || _index[i] == 316 || _index[i] == 319 || _index[i] == 470)
				cout << " true ";
			else
				cout << " false ";
			std::cout << _index[i] << ": " << "flatten_area: " << flatten_area[i] << " support points num " << support_points_num[i] << " sum_E: " << temp_sum_value[i]<<std::endl;
			//data[i] is optimal after Rough Optimize

			//Layer_Graph layer_graph(data[i]);
			//layer_graph.BuildLayerGraph();
			//layer_graph.GetInitialOPP();

			//OPP_Graph opp_graph(data[i], layer_graph.initial_opp_info);
			//opp_graph.BuildOPPGraph_G0();
			//opp_graph.MergeOPP_First_One();

			////opp_graph.MergeOPP_First_ALL_SearchTree();
			//opp_graph.GenerateFinalOPPs();
			////opp_graph.GeneratePath();

			//Visual vis;
			////if (_index[i] == 458) {
			////	cout << "^^^^^^^^^^^^^^" << _index[i] << "^^^^^^^^^^^^^^^^^^^" << endl;
			////	opp_graph.GeneratePath();
			////	//vis.generateModelForRendering_5(file_name + "_initial_opp", file_name + to_string(_index[i]) + "_initial_opp");
			////	//vis.generateModelForRendering_5(file_name + "_medium_opp", file_name + to_string(_index[i]) + "_medium_opp");
			//vis.generateModelForRendering_5(file_name + "_final_OPPs",file_name + to_string(_index[i]) + "_final_OPPs");
			////}
			////vis.generateModelForRendering_2(file_name + "_initial_opp");
			////vis.generateModelForRendering_2(file_name + "_medium_opp");
			////vis.generateModelForRendering_2(file_name + "_final_OPPs");
		}
	}
#endif
	end_time = clock();
	std::cout << "total time = " << double(end_time - start_time) / CLOCKS_PER_SEC << "s" << std::endl;
}